using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using JigLibX.Physics;
using JigLibX.Collision;
using JigLibX.Geometry;
using JigLibX.Math;
using JigLibX.Utils;
using sqengine.PhysicObjects;
using JigLibX.Vehicles;
using System.Diagnostics;

using SqEngine;
using sqengine.Components;
using SqEngine.Audio;
using sqengine.Engine.Common;

namespace sqengine.Components
{

    public class FPSWeapon : DrawableGameComponent
    {
        Game _game;
        Camera _camera;
        WeaponInfo _weapon_info;
        AudioManager _audiomanager;
        AdvancedContent _adcontent;
        Model bulletModel;
        Model _weaponmodel;
        Texture2D _weapontexture;
        bool? _calibrate;
        private Matrix[] weaponTransforms;
        public Matrix weaponWorldMatrix;
        private PlayerStats _player;
        private double _reloadtime = 200;
        private bool _canshoot = true;
        private bool _ammoempty = false;


        public FPSWeapon(Game game, Camera camera, WeaponInfo weapon_info, AudioManager audiomanager, AdvancedContent adcontent, bool? calibrate)
            : base(game)
        {
            _game = game;
            _weapon_info = weapon_info;
            _audiomanager = audiomanager;
            _adcontent = adcontent;
            _calibrate = calibrate;
            _camera = camera;

            bulletModel = adcontent.LoadModel("sphere");
            _weaponmodel = adcontent.LoadModel(_weapon_info.WeaponModel);
            _weapontexture = adcontent.LoadTexture2D(_weapon_info.WeaponTexture);

            _audiomanager.LoadSound(weapon_info.WeaponShootSound);

            weaponTransforms = new Matrix[_weaponmodel.Bones.Count];
            weaponWorldMatrix = Matrix.Identity;
        }


        public void UpdateWeapon(WeaponInfo weapon_info)
        {
            _weapon_info = weapon_info;
            _weaponmodel = _adcontent.LoadModel(_weapon_info.WeaponModel);
            _weapontexture = _adcontent.LoadTexture2D(_weapon_info.WeaponTexture);

            _audiomanager.LoadSound(weapon_info.WeaponShootSound);
            weaponTransforms = new Matrix[_weaponmodel.Bones.Count];
            weaponWorldMatrix = Matrix.Identity;
        }

        public override void Initialize()
        {
            base.Initialize();
        }

        public override void Draw(GameTime gameTime)
        {
            if (Enabled)
                DrawWeapon(_weaponmodel);
            base.Draw(gameTime);
        }


        public override void Update(GameTime gameTime)
        {
            UpdateWeapon();
            _player = ((sqengine)_game).CurrentPlayer;


            if (_reloadtime >= 0)
            {
                _canshoot = false;
                _reloadtime -= gameTime.ElapsedGameTime.TotalMilliseconds;
            }
            else
            {
                _canshoot = true;
            }

            if (_player.Ammo == 0)
            {

                _ammoempty = true;
            }
            else
            {
                _ammoempty = false;
            }


            base.Update(gameTime);
        }

        public PhysicObject Shoot(Vector3 pos, Matrix ori)
        {
            if (_canshoot)
            {
                if (!_ammoempty)
                {
                    _audiomanager.PlaySound(_weapon_info.WeaponShootSound);
                    ((sqengine)_game).CurrentPlayer.Ammo -= 1;
                    _reloadtime = 200;
                    return SpawnBullet(pos, ori);
                }
                else
                {//Click!!
                    _audiomanager.PlaySound(_weapon_info.WeaponOutOfAmmoSound);
                    return null;
                }
            }
            else
            {
                return null;
            }
        }

        private PhysicObject SpawnBullet(Vector3 pos, Matrix ori)
        {
            PhysicObject physicObj; 
            physicObj = new BulletObject(_game, bulletModel, 0.1f, ori, pos, 1f, string.Empty, ((sqengine)_game).CurrentPlayer);
            return physicObj;
        }

        private void DrawWeapon(Model _gun_model)
        {

            foreach (ModelMesh m in _gun_model.Meshes)
            {
                foreach (BasicEffect e in m.Effects)
                {
                    e.TextureEnabled = true;
                    e.Texture = _weapontexture;
                    e.EnableDefaultLighting();

                    e.World = weaponTransforms[m.ParentBone.Index] * (weaponWorldMatrix);
                    e.View = _camera.View;
                    e.Projection = _camera.Projection;
                }

                m.Draw();
            }
        }

        private void UpdateWeapon()
        {
            _weaponmodel.CopyAbsoluteBoneTransformsTo(weaponTransforms);

            if (_calibrate.Value == true)
            {
                Calibrate();
            }



            weaponWorldMatrix = _camera.WeaponWorldMatrix(-_weapon_info.Weapon_x_off,
                _weapon_info.Weapon_y_off, _weapon_info.Weapon_z_off, _weapon_info.Weapon_scale);
        }

        private void Calibrate()
        {
            KeyboardState kb = Keyboard.GetState();



            //Calibrate X
            if (kb.IsKeyDown(Keys.Y))
            {

                _weapon_info.Weapon_x_off += 0.01f;
            }

            if (kb.IsKeyDown(Keys.U))
            {

                _weapon_info.Weapon_x_off -= 0.01f;
            }

            //Calibrate Y
            if (kb.IsKeyDown(Keys.H))
            {

                _weapon_info.Weapon_y_off += 0.01f;
            }

            if (kb.IsKeyDown(Keys.J))
            {

                _weapon_info.Weapon_y_off -= 0.01f;
            }

            //Calibrate Z
            if (kb.IsKeyDown(Keys.N))
            {

                _weapon_info.Weapon_z_off += 0.01f;
            }

            if (kb.IsKeyDown(Keys.M))
            {

                _weapon_info.Weapon_z_off -= 0.01f;
            }

            //Calibrate Scale
            if (kb.IsKeyDown(Keys.I))
            {

                _weapon_info.Weapon_scale += 0.01f;
            }

            if (kb.IsKeyDown(Keys.O))
            {

                _weapon_info.Weapon_scale -= 0.01f;
            }


            if (kb.IsKeyDown(Keys.P))
            {

                SaveManager wp = new SaveManager();
                wp.SaveWeapon("c:\\" + _weapon_info.WeaponName + ".xml", _weapon_info);


            }






        }
    }
}